#ifndef __THREAD_POOL__
#define __THREAD_POOL__

#include <stdint.h>
#include <st.h>
#include "log.h"
#include "identity-pool.h"
#include "ursax.h"

#ifdef __cplusplus
extern "C" {
#endif

struct thread_pool;
void* _tp_ctor();
void _tp_dtor(void* arg);

struct workers_tracker
{
	st_thread_t waiter;
	uint32_t workers;
};

struct thread_control
{
	st_thread_t thread;
	struct thread_pool* tpool;
	void* (*do_work)(void* arg);
	void* arg;
	struct workers_tracker* tracker;
};

static inline struct thread_pool* thread_pool_new(int capacity)
{
	return (struct thread_pool*)identity_pool_new(capacity, &_tp_ctor, &_tp_dtor);
}

// tracker (optional) is used for waiting the created thread to complete
static inline st_thread_t pool_thread_create(struct thread_pool* tpool, void *(*start)(void *arg), void *arg, struct workers_tracker* tracker)
{
	struct thread_control* tc = (struct thread_control*)identity_pool_get((struct identity_pool*)tpool);
	tc->do_work = start;
	tc->tpool = tpool;
	tc->arg = arg;
	tc->tracker = tracker;
	st_thread_interrupt(tc->thread);
	return tc->thread;
}

static inline void thread_pool_delete(struct thread_pool* tpool)
{
	LOG_INFO("enter pool delete");
	identity_pool_delete((struct identity_pool*)tpool);
}

static inline void workers_tracker_init(struct workers_tracker* tracker)
{
	tracker->workers = 0;
	tracker->waiter = NULL;
}

static inline uint32_t workers_nb(struct workers_tracker* tracker)
{
	return tracker->workers;
}

static inline int workers_tracker_wait(struct workers_tracker* tracker, int second)
{
	int ret = -1;
	if(tracker->workers){
		LOG_DEBUG("workers_tracker_wait %d workers", tracker->workers);
		tracker->waiter = st_thread_self();
		ret = st_sleep(second);
		if(unlikely(ret == 0)){
			LOG_ERROR("tracker->workers is %d, wait timeout %d second", tracker->workers, second);
		}
		tracker->waiter = NULL;
		LOG_DEBUG("workers_tracker_wait workers over");
	}else{
		LOG_DEBUG("none worker to wait");
	}
	return ret; // if ret == 0 means timeout
}

#ifdef __cplusplus
}
#endif

#endif

